<?php

defined('__ENV__') or define('__ENV__', 'DEBUG');

// 信息组装与渲染输出
if (!function_exists('message')) {
    /**
     * 组装信息
     *
     * @param string $message
     * @param array $context
     * @return string
     */
    function message($message, $context = [])
    {
        $replace = array();
        if(!empty($context) and is_array($context)){
            foreach ($context as $key => $val) {
                $val = is_array($val) ? var_export($val, true) : $val;
                $replace['{' . $key . '}'] = (string)$val;
            }
        }
        return  strtr($message, $replace);
    }
}
if (!function_exists('json_print')) {
    function json_print($content)
    {
        ob_clean();
        header('Content-type: text/json');
        return json_encode($content);
    }
}
if (!function_exists('html')) {
    /**
     * 模板输出
     * @param $var
     * @param $template
     * @return string
     */
    function html($var, $template)
    {
        extract($var);
        unset($var);
        ob_start();
        /** @noinspection PhpIncludeInspection */
        include $template;
        return ob_get_clean();
    }
}
if (!function_exists('intent_ajax')) {
    /**
     * 返回数组
     * @param \J\Intent $intent
     * @param bool $status
     * @param string $msg
     * @param array $data
     * @return bool
     */
    function intent_ajax($intent, $status, $msg = null, $data = [])
    {
        $intent->value = value_ajax($status, $msg, $data);

        // 执行成功返回true或null
        return true;
    }
}
if (!function_exists('value_ajax')) {
    /**
     * 返回数组
     *
     * @param bool $status
     * @param string $msg
     * @param array $data
     * @return array
     */
    function value_ajax($status, $msg = null, $data = [])
    {
        $value = $data;

        if (!empty($msg)) {
            $value['message'] = [
                'text' => $msg,
                'type' => $status ? 'success' : 'warning',
            ];
        }

        $value['status'] = $status;

        // 执行成功返回true或null
        return $value;
    }
}
if (!function_exists('dump')) {
    /**
     * 浏览器友好的变量输出
     * @param mixed     $var   变量
     * @param boolean   $echo  是否输出 默认为true 如果为false 则返回输出字符串
     * @param string    $label 标签 默认为空
     * @param integer   $flags  htmlspecialchars flags
     * @return string
     */
    function dump($var, $echo = true, $label = null, $flags = ENT_SUBSTITUTE)
    {
        $label = (null === $label) ? '' : rtrim($label) . ':';
        ob_start();
        var_dump($var);
        $output = ob_get_clean();
        $output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output);
        if (IS_CLI) {
            $output = PHP_EOL . $label . $output . PHP_EOL;
        } else {
            if (!extension_loaded('xdebug')) {
                $output = htmlspecialchars($output, $flags);
            }
            $output = '<pre>' . $label . $output . '</pre>';
        }
        if ($echo) {
            echo ($output);
            return null;
        } else {
            return $output;
        }
    }
}
if (!function_exists('format_memory_size')) {
    /**
     * 存储容量格式化
     *
     * @param int|float $size 容量
     * @return string
     */
    function format_memory_size($size) : string
    {
        $a = ['B', 'KB', 'MB', 'GB', 'TB'];
        $pos = 0;
        while ($size >= 1024) {
            $size /= 1024;
            $pos++;
        }
        return round($size) . " " . $a[$pos];
    }
}

//  类相关函数
if (!function_exists('is_classname')) {
    function is_classname($class)
    {
        /**
         * 反斜线在单引号字符串和双引号字符串中都有特殊含义，
         * 因此要匹配一个反斜线， 模式中必须写为 ”\\\\”。
         * 如: '/\\/'
         *     首先它作为字符串，反斜线会进行转义， 那么转义后的结果是/\/，
         *     而正则表达式引擎也认为 \ 是转义标记，它会将分隔符 / 进行转义， 从而得到的是一个错误。
         *  因此，需要 4 个反斜线才可以匹配一个反斜线。
         */
        return preg_match('%^[\\\\a-z][\\\\_a-z0-9]*$%i', $class);
    }
}
if (!function_exists('class_basename')) {
    /**
     * 返回不包含命名空间的类名
     *
     * @param  string|object $class
     * @return string
     */
    function class_basename($class)
    {
        $class = is_object($class) ? get_class($class) : $class;
        return basename(str_replace('\\', '/', $class));
    }
}
if (!function_exists('class_namespace')) {
    /**
     * 返回命名空间
     * @param string|object $class
     * @return string
     */
    function class_namespace($class)
    {
        $class = is_object($class) ? get_class($class) : $class;

        $pos = strrpos($class, '\\');

        return  ($pos !== false) ? substr($class, 0, $pos) : '';
    }
}
if (!function_exists('separate_classname')) {
    /**
     * 拆分类名
     * @param string $class
     * @param string $classname
     * @param string $namespace
     * @return bool
     */
    function separate_classname($class, &$classname, &$namespace)
    {
        if (!is_classname($class)) return false;

        $classname = class_basename($class);
        $namespace = class_namespace($class);

        return true;
    }
}

//  数组函数
if (!function_exists('array_get')) {
    /**
     * Get an item from an array using "dot" notation.
     *
     * @param  array $array
     * @param  string $key
     * @param  mixed $default
     * @return mixed
     */
    function array_get($array, $key, $default = null)
    {
        array_has($array,$key,$default);

        return $default;
    }
}
if (!function_exists('array_has')) {
    /**
     * Check if an item exists in an array using "dot" notation.
     *
     * @param array $array
     * @param string $key
     * @param mixed $value
     * @return bool
     */
    function array_has($array, $key, &$value = null)
    {
        if (empty($array) || is_null($key)) return false;

        foreach (explode('.', $key) as $segment) {
            if (!is_array($array) || !array_key_exists($segment, $array)) {
                return false;
            }
            $array = $array[$segment];
        }
        $value = $array;
        return true;
    }
}
if (!function_exists('array_set')) {
    /**
     * Set an array item to a given value using "dot" notation.
     *
     * If no key is given to the method, the entire array will be replaced.
     *
     * @param  array $array
     * @param  string $key
     * @param  mixed $value
     * @return bool  isModified
     */
    function array_set(&$array, $key, $value)
    {
        if (is_null($key)) return false;

        $keys = explode('.', $key);

        $modified = false;
        while (count($keys) > 0) {
            $key = array_shift($keys);
            // If the key doesn't exist at this depth, we will just create an empty array
            // to hold the next value, allowing us to create the arrays to hold final
            // values at the correct depth. Then we'll keep digging into the array.
            if (!isset($array[$key]) || !is_array($array[$key])) {
                $array[$key] = [];
                $modified = true;
            }

            $array =& $array[$key];
        }

        if ($array === $value) return $modified;

        $array = $value;

        return true;
    }
}
if (!function_exists('array_forget')) {
    /**
     * Remove one or many array items from a given array using "dot" notation.
     *
     * @param  array $array
     * @param  array|string $keys
     * @return bool isModified
     */
    function array_forget(&$array, $keys)
    {
        $original =& $array;

        $modified = false;

        foreach ((array)$keys as $key) {
            $parts = explode('.', $key);
            while (count($parts) > 1) {
                $part = array_shift($parts);
                if (isset($array[$part]) && is_array($array[$part])) {
                    $array =& $array[$part];
                }
            }
            unset($array[array_shift($parts)]);
            $modified = true;
            // clean up after each pass
            $array =& $original;
        }

        return $modified;
    }
}
if (!function_exists('array_complete')) {
    /**
     * 完整化数组 [a=>A,b] => [a=>A,b=>default]
     * @param $array
     * @param mixed $default
     * @return array
     */
    function array_complete($array, $default = null)
    {
        if (!is_array($array)) return [$array => $default];
        $result = [];
        foreach ($array as $key => $value) {
            if (is_int($key) and is_string($value)) {
                $result[$value] = $default;
            } else {
                $result[$key] = $value;
            }
        }
        return $result;
    }
}
if (!function_exists('array_column_unique')) {
    /**
     * Returns an array of unique values representing a single column from the input
     * array.
     * @param array $array A multi-dimensional array from which to pull a
     *     column of values.
     * @param mixed $columnKey The column of values to return.
     * @return array
     */
    function array_column_unique($array, $columnKey)
    {
        if(!is_array($array)) return $array;

        $result = [];
        foreach ($array as $subArray) {
            if (!is_array($subArray) or !array_key_exists($columnKey, $subArray)) {
                continue;
            } elseif (is_scalar($subArray[$columnKey]) ) {
                $result[$subArray[$columnKey]] = true;
            }
        }
        return array_keys($result);
    }
}
if (!function_exists('array_isset')) {
    /**
     * isset语句函数 isset($arr[$key])?$arr[$key]:default
     *
     * @param mixed $arr
     * @param $key
     * @param  $default
     * @return mixed|null
     */
    function array_isset($arr,$key, $default = null)
    {
        return  ((is_array($arr) and isset($arr[$key]))?$arr[$key]:$default);
    }
}
if (!function_exists('array_remove')) {
    function array_remove(array &$array, $key,  $default = null)
    {
        if(array_has($array,$key,$value)){
            array_forget($array,$key);
            return $value;
        }
        return $default;
    }
}
if (!function_exists('is_list')) {
    /**
     * 数组键为 [0, 1, ..., n]
     * @param array $array
     * @return bool
     */
    function is_list($array)
    {
        return array_keys($array) === range(0, count($array) - 1);
    }
}
if (!function_exists('array2bit')) {
    function array2bit($arr)
    {
        if(empty($arr) or !is_array($arr)) return 0;

        $bit = 0;
        foreach ($arr as $a){
            if($a>31) continue;
            $bit |= 1<<$a;
        }
        return $bit;
    }
}
if (!function_exists('bit2array')) {
    function bit2array($bit)
    {
        $bit = $bit & 0x7fffffff;
        $r = [];
        $index = 0;
        while($bit){
            if($bit & 1) $r[] = $index++;

            $bit = $bit >> 1;
        }
        return $r;
    }
}
if (!function_exists('array_assign')) {
    /**
     * 数组适应性赋值操作
     * @param array $arr
     * @param array|string $name
     * @param $value
     * @return array
     */
    function array_assign(array $arr, $name = null,$value = null)
    {
        if($name === null) return $arr;

        if(is_array($name)) return array_merge_recursive($arr,$name);
        // TODO 请注意$name类型，这里可能不能赋值
        $arr[$name] = $value;
        return $arr;
    }
}
if (!function_exists('array_every')) {
    function array_every($array, $callback){

        foreach ($array as $key => $value) {
            if ($callback($value, $key)) continue;
            return false;
        }
        return true;
    }
}
if (!function_exists('array_pass')) {
    /**
     * 按照$config的设定, 提取$form中的数据
     *
     * @param array $config 设置
     * @param array $from 来源
     * @param array $to 去向
     * @param bool $toFirst 原默认值优先
     * @return array
     */
    function array_pass(array $config, array $from, array &$to = [], $toFirst = true)
    {
        array_walk($config, function ($value, $key) use ($from, &$to, $toFirst) {
            if (is_array($value)) {
                $index = $value[0];
                $default = array_isset($value, 1, null);
            } else {
                $index = $value;
                $default = null;
            }
            if (empty($index)) $index = $key;
            if ($toFirst) $default = array_isset($to, $key, $default);
            $to[$key] = array_isset($from, $index, $default);
        });
        return $to;
    }
}

//  字符串计算函数
if (!function_exists('str_random')) {
    /**
     * Generate a more truly "random" alpha-numeric string.
     *
     * @param  int $length
     * @param bool $useNum
     * @return string
     */
    function str_random($length = 16,$useNum = true)
    {
        if (function_exists('openssl_random_pseudo_bytes')) {
            $bytes = openssl_random_pseudo_bytes($length * 2);
            if ($bytes !== false) {
                $filter = ($useNum) ? ['/', '+', '='] :
                    ['/', '+', '=','1','2','3','4','5','6','7','8','9','0'];
                return substr(str_replace($filter, '', base64_encode($bytes)), 0, $length);
            }
        }
        $pool = ($useNum) ? '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' :
            'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

        return substr(str_shuffle(str_repeat($pool, $length)), 0, $length);
    }
}
if (!function_exists('str_is')) {
    /**
     * Determine if a given string matches a given pattern.
     *
     * @param  string $pattern
     * @param  string $value
     * @return bool
     */
    function str_is($pattern, $value)
    {
        if ($pattern == $value) return true;

        $pattern = preg_quote($pattern, '#');

        // Asterisks are translated into zero-or-more regular expression wildcards
        // to make it convenient to check if the strings starts with the given
        // pattern such as "library/*", making any string check convenient.
        $pattern = str_replace('\*', '.*', $pattern) . '\z';

        return (bool)preg_match('#^' . $pattern . '#', $value);
    }
}
if (!function_exists('e')) {
    /**
     * Escape HTML entities in a string.
     *
     * @param  string $value
     * @return string
     */
    function e($value)
    {
        return htmlentities($value, ENT_QUOTES, 'UTF-8', false);
    }
}
if (!function_exists('xorTokens')) {
    /**
     * Returns the XOR result of two strings.
     * If the two strings are of different lengths, the shorter one will be padded to the length of the longer one.
     * @param string $token1
     * @param string $token2
     * @return string the XOR result
     */
    function xorTokens($token1, $token2)
    {
        $n1 = mb_strlen($token1, '8bit');
        $n2 = mb_strlen($token2, '8bit');
        if ($n1 > $n2) {
            $token2 = str_pad($token2, $n1, $token2);
        } elseif ($n1 < $n2) {
            $token1 = str_pad($token1, $n2, $n1 === 0 ? ' ' : $token1);
        }

        return $token1 ^ $token2;
    }
}
if (!function_exists('byteSubStr')) {
    function byteSubStr($string, $start, $length = null)
    {
        return mb_substr($string, $start, $length === null ? mb_strlen($string, '8bit') : $length, '8bit');
    }
}

// 网络
if (!function_exists('vars_form_path')) {
    /**
     * 将PATH(e/f/p/q)解析到数组里(e=>f,p=>q)
     * @param string $value  PATH
     * @param array  $param  承载数组
     */
    function vars_form_path($value,&$param)
    {
        try{
            preg_replace_callback(
                '/([A-Za-z]+)\/([A-Za-z0-9]+)/',
                function($match) use(&$param){
                    $param[ strtolower($match[1]) ] = strip_tags($match[2]);
                },
                $value
            );
        } catch (Exception $e){}
    }
}
if (!function_exists('http_method')) {
    function http_method()
    {
        static $method = null;
        if(!$method){
            $method =  (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) ?
                strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']) :
                isset($_SERVER['REQUEST_METHOD']) ? strtoupper($_SERVER['REQUEST_METHOD']) : 'GET';
        }
        return $method;
    }
}
if (!function_exists('get_client_ip')){
    /**
     * 获取客户端IP地址
     * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字
     * @param boolean $adv 是否进行高级模式获取（有可能被伪装）
     * @return mixed
     */
    function get_client_ip($type = 0, $adv=false) {
        $type       =  $type ? 1 : 0;
        static $ip  =   NULL;
        if ($ip !== NULL) return $ip[$type];
        if ($adv) {
            if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                $arr    =   explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
                $pos    =   array_search('unknown',$arr);
                if(false !== $pos) unset($arr[$pos]);
                $ip     =   trim($arr[0]);
            }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
                $ip     =   $_SERVER['HTTP_CLIENT_IP'];
            }elseif (isset($_SERVER['REMOTE_ADDR'])) {
                $ip     =   $_SERVER['REMOTE_ADDR'];
            }
        } elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        // IP地址合法验证
        $long = sprintf("%u",ip2long($ip));
        $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
        return $ip[$type];
    }
}
if (!function_exists('parse_accept_header')){
    /**
     * 解析信息头
     *
     * 本函数自动排序
     *
     * ```php
     * $header = 'text/plain; q=0.5, application/json; version=1.0, application/xml; version=2.0;';
     * $accepts = $request->parseAcceptHeader($header);
     * print_r($accepts);
     * // displays:
     * // [
     * //     'application/json' => ['q' => 1, 'version' => '1.0'],
     * //      'application/xml' => ['q' => 1, 'version' => '2.0'],
     * //           'text/plain' => ['q' => 0.5],
     * // ]
     * ```
     *
     * @param string $header
     * @return array
     */
    function parse_accept_header($header)
    {
        $accepts = [];
        foreach (explode(',', $header) as $i => $part) {
            $params = preg_split('/\s*;\s*/', trim($part), -1, PREG_SPLIT_NO_EMPTY);
            if (empty($params)) continue;

            $values = [
                'q' => [$i, array_shift($params), 1],
            ];
            foreach ($params as $param) {
                if (strpos($param, '=') !== false) {
                    list ($key, $value) = explode('=', $param, 2);
                    if ($key === 'q') {
                        $values['q'][2] = (double)$value;
                    } else {
                        $values[$key] = $value;
                    }
                } else {
                    $values[] = $param;
                }
            }
            $accepts[] = $values;
        }

        usort($accepts, function ($a, $b) {
            $a = $a['q']; // index, name, q
            $b = $b['q'];
            if ($a[2] > $b[2]) {
                return -1;
            } elseif ($a[2] < $b[2]) {
                return 1;
            } elseif ($a[1] === $b[1]) {
                return $a[0] > $b[0] ? 1 : -1;
            } elseif ($a[1] === '*/*') {
                return 1;
            } elseif ($b[1] === '*/*') {
                return -1;
            } else {
                $wa = $a[1][strlen($a[1]) - 1] === '*';
                $wb = $b[1][strlen($b[1]) - 1] === '*';
                if ($wa xor $wb) {
                    return $wa ? 1 : -1;
                } else {
                    return $a[0] > $b[0] ? 1 : -1;
                }
            }
        });

        $result = [];
        foreach ($accepts as $accept) {
            $name = $accept['q'][1];
            $accept['q'] = $accept['q'][2];
            $result[$name] = $accept;
        }

        return $result;
    }
}
if (!function_exists('current_pathinfo')){
    function current_pathinfo(){
        return isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '';
    }
}
if (!function_exists('http_version')){
    function http_version()
    {
        static $version = null;
        if (!$version) {
            $version = isset($_SERVER['SERVER_PROTOCOL']) && $_SERVER['SERVER_PROTOCOL'] === 'HTTP/1.0' ?
                '1.0' : '1.1';
        }
        return $version;
    }
}
if (!function_exists('get_acceptable_content_types')){
    function get_acceptable_content_types()
    {
        static $contentTypes = null;
        if ($contentTypes === null) {
            $contentTypes = isset($_SERVER['HTTP_ACCEPT']) ?
                parse_accept_header($_SERVER['HTTP_ACCEPT']) : [];
        }

        return $contentTypes;
    }
}
if (!function_exists('isAjax')){
    /**
     * Returns whether this is an AJAX (XMLHttpRequest) request.
     * @return boolean whether this is an AJAX (XMLHttpRequest) request.
     */
    function isAjax()
    {
        return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest';
    }
}
if (!function_exists('isPjax')){
    /**
    * Returns whether this is a PJAX request
    * @return boolean whether this is a PJAX request
    */
    function isPjax()
    {
        return isAjax() && !empty($_SERVER['HTTP_X_PJAX']);
    }
}
if (!function_exists('isInvalidStatusCode')) {
    /**
     * @param int $statusCode 状态码
     * @return bool 是否为有效的状态码
     */
    function isInvalidStatusCode($statusCode)
    {
        return $statusCode < 100 || $statusCode >= 600;
    }
}
if (!function_exists('dsn2config')) {
    /**
     * 将DSN转化为数组
     *
     * 格式： mysql://user:pass@host:port/name?param1=val1&param2=val2#utf8
     *
     * @param $dsn
     * @return array|bool
     */
    function dsn2config($dsn)
    {
        if(empty($dsn)) return false;

        $temp = parse_url($dsn);
        if(!$temp) return false;

        $config = [];

        $config = array_pass([
            'type'    => ['scheme', 'mysql'],
            'host'    => [null, 'localhost'],
            'port'    => [null, 3306],
            'user'    => null,
            'pass'    => null,
            'charset' => ['fragment','utf8']
        ], $temp, $config);

        if(isset($temp['path'])) $config['name'] = substr($config['path'],1);

        $config['params'] = [];
        if(isset($temp['query'])) parse_str($temp['query'],$config['params']);

        return $config;
    }
}
if (!function_exists('isJsonSend')) {
    function isJsonSend()
    {
        $type = array_keys(get_acceptable_content_types())[0];
        return isAjax() or isPjax() or stristr($type, 'json') !== false;
    }
}

// 验证转化
if (!function_exists('convert_float')) {
    function convert_float(&$var)
    {
        if (!is_numeric($var) and !empty($var)) return false;
        $var = floatval($var);
        return true;
    }
}
if (!function_exists('convert_int')) {
    function convert_int(&$var)
    {
        if (!is_numeric($var)) return false;
        $var = intval($var);
        return true;
    }
}
if (!function_exists('valid_name')) {
    function valid_name($var)
    {
        if (empty($var)) return false;

        $match = '/^[_\w\d\x{4e00}-\x{9fa5}]*$/iu';
        return preg_match($match, $var);
    }
}
if (!function_exists('convert_id')) {
    function convert_id(&$id)
    {
        if (is_array($id)) {
            // 2018/2/5 添加索引判断:索引必须为整数(本身是一维数组)
            foreach ($id as $k=>&$v) if (!is_int($k) or !convert_id($v)) return false;
            return true;
        }
        if (!empty($id) and !is_numeric($id)) return false;
        $id = (int)$id;
        return $id >= 0;
    }
}
if (!function_exists('convert_bool')) {
    /**
     * $value === true ：<>0 , 'true', '1', stdClass, !Empty, 'yes', 'on'
     * @param $value
     */
    function convert_bool(&$value)
    {
        $value = (is_string($value) ? filter_var(
            $value,
            FILTER_VALIDATE_BOOLEAN,
            FILTER_NULL_ON_FAILURE
        ) : (bool)$value);
    }
}

// DI
if (!function_exists('get_instance')) {
    function get_instance($concrete, $arguments, $interface = null)
    {
        if(!class_exists($concrete)) return null;

        if(!empty($interface) and !is_subclass_of($concrete, $interface)) return null;

        if (empty($arguments)) return new $concrete;

        try{
            //带参数的类实例化，使用反射
            $class = new \ReflectionClass($concrete);
            if (count($class->getConstructor()->getParameters()) === 0)
                return $class->newInstance();
            return $class->newInstanceArgs($arguments);
        }catch(\Exception $e){
            return null;
        }
    }
}

/**
 * @return \J\Application
 */
function app()
{
    return \J\Application::getInstance();
}
/**
 * 链接表名称
 * @param string $a
 * @param string $b
 * @return string
 */
function default_table_linker($a,$b)
{
    return $a.'_'.$b;
}
/**
 * 配置文件文件名生成函数
 * @param $dir
 * @return string
 */
function config_file_name($dir)
{
    return $dir . DS .'conf' . DS . \strtolower(__ENV__) . '.php';
}
/**
 * 创建在线验证
 *
 * @param \J\Schema\IElement $element
 * @param $holder
 * @return array|mixed
 */
function make_element_validator(\J\Schema\IElement $element, $holder)
{
    $validator = array_map(function ($valid) {
        if (is_string($valid)) return ['type' => strtolower($valid)];
        return $valid;
    }, (array)($element->getAttribute()->get('valid', [])));
    // 必填验证
    if ($element->must()) {
        $v = [
            'required' => true,
            'message' => '请输入' . $element->getLabel(),
            'trigger' => (in_array($holder,
                ['radio', 'checkbox', 'select', 'switch', 'cascader']
            )) ? 'blur' : 'change'
        ];
        if (in_array($holder, ['DateTimePicker', 'TimePicker', 'DatePicker'])) {
            $v['type'] = 'date';
        } elseif ($holder == 'checkbox') {
            $v['type'] = 'array';
        }
        $validator[] = $v;
    }

    return $validator;
}
/**
 * 域列表
 *
 * @param array $config
 * @return array|string
 */
function get_elements($config)
{
    return array_isset($config, \J\Schema\Syntax::KEY_ELEMENTS, \J\Schema\Syntax::KEY_ALL);
}
/**
 * 默认中间件创建函数
 * @return Closure
 */
function default_middleware_creator()
{
    return function ($class)
    {
        $class = '\\J\\Middleware\\'.ucfirst($class);
        if(class_exists($class)){
            /** @var \J\Middleware $obj */
            return  new $class;
        }
        return null;
    };
}